/*******************************************************************************
 * Copyright (c) 2012, G. Weirich and Elexis
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    G. Weirich - initial implementation
 *******************************************************************************/

package ch.elexis.easy.ui;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.part.ViewPart;

import ch.elexis.core.ElexisCoreException;
import ch.elexis.core.admin.InsufficientRightsException;
import ch.elexis.core.data.IActionDefinition;
import ch.elexis.easy.ui.elements.IElexisEasyComponent;

public class View extends ViewPart {
	public static final String ID = "ch.elexis.easy.core.view";
	StackLayout componentStack = new StackLayout();
	StackLayout actionStack = new StackLayout();
	private IConfigurationElement[] configurationElements;
	FormToolkit tk = new FormToolkit(Display.getCurrent());
	private Composite cApps;
	private Composite cActions;
	private MainPanel mainPanel;
	private ActionsPanel leftPanel;
	
	Map<String, CTabFolder> appHash = new LinkedHashMap<String, CTabFolder>();
	Map<String, ActionsPanel> actionsHash = new LinkedHashMap<String, ActionsPanel>();
	
	private IActionDefinition actionBack = new IActionDefinition() {
		
		@Override
		public String getToolTipText(){
			return "back to overview";
		}
		
		@Override
		public String getText(){
			return "Back";
		}
		
		@Override
		public Object execute(Object params) throws InsufficientRightsException{
			componentStack.topControl = mainPanel;
			cApps.layout();
			actionStack.topControl=leftPanel;
			cActions.layout();
			return null;
		}
	};
	private SelectionAdapter cTabClicked = new SelectionAdapter() {
		@Override
		public void widgetSelected(SelectionEvent e){
			CTabFolder source = (CTabFolder) e.widget;
			CTabItem top = source.getSelection();
			String subname = (String) top.getData("subname");
			if (top.getControl() == null) {
				IElexisEasyComponent eec = (IElexisEasyComponent) source.getData("component");
				Control ctrl = eec.createComponent(source, subname);
				top.setControl(ctrl);
				ActionsPanel actionsPanel = actionsHash.get(subname);
				if (actionsPanel == null) {
					ArrayList<IActionDefinition> al =
						new ArrayList<IActionDefinition>(Arrays.asList(eec.getActions(subname)));
					al.add(0, actionBack);
					actionsPanel = new ActionsPanel(cActions, al.toArray(new IActionDefinition[0]));
					actionsHash.put(subname, actionsPanel);
				}
			}
			actionStack.topControl = actionsHash.get(subname);
			cActions.layout();
		}
		
	};
	
	private void activateComponent(String name) throws ElexisCoreException{
		CTabFolder ctab = appHash.get(name);
		if (ctab == null) {
			for (IConfigurationElement ice : configurationElements) {
				if (ice.getAttribute("name").equals(name)) {
					try {
						IElexisEasyComponent eec =
							(IElexisEasyComponent) ice.createExecutableExtension("Class");
						ctab = new CTabFolder(cApps, SWT.TOP);
						ctab.setData("component", eec);
						IConfigurationElement[] subapps = ice.getChildren("subapplication");
						for (IConfigurationElement subapp : subapps) {
							String subname = subapp.getAttribute("name");
							String subtitle = subapp.getAttribute("title");
							CTabItem item = new CTabItem(ctab, SWT.NONE);
							item.setText(subtitle);
							item.setData("subname", subname);
						}
						ctab.addSelectionListener(cTabClicked);
						appHash.put(name, ctab);
					} catch (CoreException ce) {
						throw new ElexisCoreException(ce.getMessage());
					}
				}
			}
		}
		if (ctab.getSelection() == null) {
			ctab.setSelection(0);
			Event event = new Event();
			event.widget = ctab;
			event.item = ctab.getSelection();
			cTabClicked.widgetSelected(new SelectionEvent(event));
		}
		componentStack.topControl = ctab;
		cApps.layout();
		String subname=(String)ctab.getSelection().getData("subname");
		actionStack.topControl = actionsHash.get(subname);
		cActions.layout();
	}
	
	public void createPartControl(Composite parent){
		parent.setLayout(new FillLayout());
		SashForm sash = new SashForm(parent, SWT.HORIZONTAL);
		ScrolledForm sfLeft = tk.createScrolledForm(sash);
		sfLeft.getBody().setLayout(new GridLayout());
		final ScrolledForm sfRight = tk.createScrolledForm(sash);
		sash.setWeights(new int[] {
			1, 3
		});
		sfLeft.getBody().setLayout(new FillLayout());
		cActions = tk.createComposite(sfLeft.getBody());
		cActions.setLayout(actionStack);
		sfRight.getBody().setLayout(new FillLayout());
		cApps = tk.createComposite(sfRight.getBody());
		cApps.setLayout(componentStack);
		mainPanel = new MainPanel(cApps);
		collectComponents();
		List<IActionDefinition> actions = new ArrayList<IActionDefinition>();
		for (IConfigurationElement ice : configurationElements) {
			final String title = ice.getAttribute("title");
			final String name = ice.getAttribute("name");
			IActionDefinition action = new IActionDefinition() {
				
				@Override
				public String getText(){
					return title;
				}
				
				@Override
				public String getToolTipText(){
					return MessageFormat.format("Activate component {0}", title);
				}
				
				@Override
				public Object execute(Object params) throws InsufficientRightsException{
					try {
						activateComponent(name);
					} catch (ElexisCoreException e) {
						e.printStackTrace();
						throw new InsufficientRightsException("ElexisCofeException: "
							+ e.getMessage());
					}
					return null;
				}
				
			};
			actions.add(action);
		}
		leftPanel = new ActionsPanel(cActions, actions.toArray(new IActionDefinition[0]));
		actionStack.topControl = leftPanel;
		cActions.layout();
		componentStack.topControl = mainPanel;
		cApps.layout();
		sfLeft.setText("Left");
		sfRight.setText("Right");
		tk.adapt(parent);
		parent.setSize(800, 600);
		parent.pack();
	}
	
	private void collectComponents(){
		LinkedList<IConfigurationElement> ret = new LinkedList<IConfigurationElement>();
		IExtensionRegistry exr = Platform.getExtensionRegistry();
		IExtensionPoint exp = exr.getExtensionPoint("ch.elexis.easy.component");
		if (exp != null) {
			IExtension[] extensions = exp.getExtensions();
			for (IExtension ex : extensions) {
				IConfigurationElement[] elems = ex.getConfigurationElements();
				for (IConfigurationElement el : elems) {
					ret.add(el);
				}
			}
			
		}
		configurationElements = ret.toArray(new IConfigurationElement[0]);
	}
	
	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus(){
		
	}
}